from PIL import Image, ImageTk
import win32clipboard
from io import BytesIO
import pyautogui
import time
import tkinter as tk
from tkinter import messagebox, simpledialog, ttk, filedialog
import threading
import pyperclip
import os
import sys

# 尝试导入pandas和相关Excel处理库
try:
    import pandas as pd

    PANDAS_AVAILABLE = True
except ImportError:
    PANDAS_AVAILABLE = False

try:
    import openpyxl

    OPENPYXL_AVAILABLE = True
except ImportError:
    OPENPYXL_AVAILABLE = False


class ClickPointsApp:
    def __init__(self, root):
        self.root = root
        self.root.title("屏幕点击和输入工具")
        self.root.geometry("700x700")

        self.points = []  # 存储点信息: (x, y, text, click_type, delay_after, is_image)
        self.always_on_top = tk.BooleanVar(value=True)
        self.is_running = False
        self.is_excel_execution_running = False
        self.current_image_path = None
        self.current_image_data = None

        self.root.attributes('-topmost', self.always_on_top.get())
        self.create_widgets()

    def create_widgets(self):
        # 窗口置顶
        tk.Checkbutton(self.root, text="窗口始终置顶", variable=self.always_on_top,
                       command=lambda: self.root.attributes('-topmost', self.always_on_top.get())).pack(pady=5)

        # 说明标签
        tk.Label(self.root, text="点击'记录点'按钮后，将鼠标移动到目标位置，\n按空格键记录坐标点",
                 wraplength=550, justify="left").pack(pady=10)

        # 记录点按钮
        self.record_btn = tk.Button(self.root, text="记录点", command=self.start_recording)
        self.record_btn.pack(pady=5)

        # 点列表显示
        columns = ("序号", "坐标", "输入内容", "点击类型", "延迟")
        self.points_treeview = ttk.Treeview(self.root, columns=columns, show="headings", height=8)
        for col in columns:
            self.points_treeview.heading(col, text=col)
            self.points_treeview.column(col, width=80)
        self.points_treeview.column("输入内容", width=150)
        self.points_treeview.pack(pady=10, padx=10, fill=tk.BOTH, expand=True)

        # 点操作设置
        point_ops_frame = tk.Frame(self.root)
        point_ops_frame.pack(pady=5)

        tk.Label(point_ops_frame, text="点击类型:").pack(side=tk.LEFT, padx=5)
        self.click_type_var = tk.StringVar(value="单击")
        ttk.Combobox(point_ops_frame, textvariable=self.click_type_var,
                     values=["单击", "双击", "右键点击"], state="readonly", width=10).pack(side=tk.LEFT, padx=5)

        tk.Label(point_ops_frame, text="延迟(秒):").pack(side=tk.LEFT, padx=5)
        self.delay_after_var = tk.StringVar(value="0.5")
        tk.Entry(point_ops_frame, textvariable=self.delay_after_var, width=5).pack(side=tk.LEFT, padx=5)

        tk.Button(point_ops_frame, text="更新选中点", command=self.update_selected_point).pack(side=tk.LEFT, padx=10)

        # 输入设置
        input_frame = tk.Frame(self.root)
        input_frame.pack(pady=5)

        tk.Label(input_frame, text="输入方式:").pack(side=tk.LEFT, padx=5)
        self.input_method_var = tk.StringVar(value="paste")
        for text, value in [("粘贴方式", "paste"), ("键盘方式", "keyboard"), ("图片输入", "image")]:
            tk.Radiobutton(input_frame, text=text, variable=self.input_method_var, value=value).pack(side=tk.LEFT,
                                                                                                     padx=5)

        # 输入选项
        input_options_frame = tk.Frame(self.root)
        input_options_frame.pack(pady=5)

        self.clear_before_input = tk.BooleanVar(value=True)
        tk.Checkbutton(input_options_frame, text="输入前清除内容", variable=self.clear_before_input).pack(side=tk.LEFT, padx=5)

        self.enter_after_input = tk.BooleanVar(value=False)
        tk.Checkbutton(input_options_frame, text="输入后按回车", variable=self.enter_after_input).pack(side=tk.LEFT, padx=5)

        # 全局设置
        config_frame = tk.Frame(self.root)
        config_frame.pack(pady=5)

        for label, var, default in [("全局延迟(秒):", "global_delay_var", "3"),
                                    ("全局间隔(秒):", "global_interval_var", "0.5")]:
            setattr(self, var, tk.StringVar(value=default))
            tk.Label(config_frame, text=label).pack(side=tk.LEFT, padx=5)
            tk.Entry(config_frame, textvariable=getattr(self, var), width=5).pack(side=tk.LEFT, padx=5)

        # 操作按钮
        btn_frame = tk.Frame(self.root)
        btn_frame.pack(pady=10)

        buttons = [
            ("执行所有操作", self.start_execution, "execute_btn", tk.DISABLED),
            ("停止执行", self.stop_execution, "stop_btn", tk.DISABLED),
            ("执行Excel数据", self.start_excel_execution, "excel_execute_btn", tk.DISABLED),
            ("停止Excel执行", self.stop_excel_execution, "stop_excel_execute_btn", tk.DISABLED),
            ("编辑点", self.edit_point, None, tk.NORMAL),
            ("删除选中点", self.delete_selected_point, None, tk.NORMAL),
            ("清除所有点", self.clear_points, None, tk.NORMAL),
            ("测试输入", self.test_input, None, tk.NORMAL),
            ("选择图片", self.select_image, None, tk.NORMAL),
            ("Excel数据处理", self.open_excel_tool, None, tk.NORMAL),
            ("退出", self.root.quit, None, tk.NORMAL)
        ]

        for text, command, attr, state in buttons:
            btn = tk.Button(btn_frame, text=text, command=command, state=state)
            btn.pack(side=tk.LEFT, padx=5)
            if attr:
                setattr(self, attr, btn)

        # 状态标签
        self.status_label = tk.Label(self.root, text="就绪", relief=tk.SUNKEN, anchor=tk.W)
        self.status_label.pack(fill=tk.X, padx=5, pady=5)

    def start_recording(self):
        self.record_btn.config(state=tk.DISABLED)
        self.root.iconify()
        messagebox.showinfo("提示", "将鼠标移动到目标位置后按空格键记录点。\n按ESC键退出记录模式。")
        self.root.bind('<Key>', self.record_point)

    def record_point(self, event):
        if event.keysym == 'space':
            x, y = pyautogui.position()

            if self.input_method_var.get() == "image":
                if not self.current_image_path:
                    messagebox.showwarning("警告", "请先选择图片")
                    return
                text, is_image = self.current_image_path, True
            else:
                text, is_image = simpledialog.askstring("输入文字", "如果需要在此位置输入文字，请输入内容:\n(留空表示只点击不输入)") or "", False

            click_type = self.click_type_var.get()
            delay_after = float(self.delay_after_var.get())

            self.points.append((x, y, text, click_type, delay_after, is_image))
            self.update_points_display()

            if self.points:
                self.execute_btn.config(state=tk.NORMAL)

        elif event.keysym == 'Escape':
            self.root.deiconify()
            self.record_btn.config(state=tk.NORMAL)
            self.root.unbind('<Key>')

    def select_image(self):
        file_path = filedialog.askopenfilename(
            title="选择图片文件",
            filetypes=[("图片文件", "*.png *.jpg *.jpeg *.gif *.bmp *.ico"), ("所有文件", "*.*")]
        )

        if file_path:
            self.current_image_path = file_path
            try:
                with open(file_path, 'rb') as f:
                    self.current_image_data = f.read()
                messagebox.showinfo("成功", f"已选择图片: {os.path.basename(file_path)}")
            except Exception as e:
                messagebox.showerror("错误", f"无法读取图片: {str(e)}")

    def copy_image_to_clipboard(self, image_path):
        try:
            image = Image.open(image_path)
            output = BytesIO()
            image.save(output, "BMP")
            data = output.getvalue()[14:]
            output.close()

            win32clipboard.OpenClipboard()
            win32clipboard.EmptyClipboard()
            win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
            win32clipboard.CloseClipboard()
            return True
        except Exception as e:
            print(f"复制图片到剪贴板失败: {str(e)}")
            return False

    def update_points_display(self):
        for item in self.points_treeview.get_children():
            self.points_treeview.delete(item)

        for i, (x, y, text, click_type, delay_after, is_image) in enumerate(self.points):
            display_text = f"[图片] {os.path.basename(text)}" if is_image else text
            self.points_treeview.insert("", "end",
                                        values=(i + 1, f"({x}, {y})", display_text, click_type, f"{delay_after}秒"))

    def update_selected_point(self):
        selection = self.points_treeview.selection()
        if not selection:
            messagebox.showwarning("警告", "请先选择一个点")
            return

        index = self.points_treeview.index(selection[0])
        x, y, text, _, _, is_image = self.points[index]

        self.points[index] = (x, y, text, self.click_type_var.get(), float(self.delay_after_var.get()), is_image)
        self.update_points_display()
        messagebox.showinfo("成功", "已更新选中点的设置")

    def delete_selected_point(self):
        selection = self.points_treeview.selection()
        if not selection:
            messagebox.showwarning("警告", "请先选择一个点")
            return

        self.points.pop(self.points_treeview.index(selection[0]))
        self.update_points_display()

        if not self.points:
            self.execute_btn.config(state=tk.DISABLED)

    def edit_point(self):
        selection = self.points_treeview.selection()
        if not selection:
            messagebox.showwarning("警告", "请先选择一个点进行编辑")
            return

        index = self.points_treeview.index(selection[0])
        x, y, text, click_type, delay_after, is_image = self.points[index]

        new_x = simpledialog.askinteger("编辑坐标", "输入新的X坐标:", initialvalue=x)
        new_y = simpledialog.askinteger("编辑坐标", "输入新的Y坐标:", initialvalue=y)

        if new_x is None or new_y is None:
            return

        if is_image:
            if messagebox.askyesno("编辑内容", "当前点是图片，是否重新选择图片？\n选择'否'将允许您输入文本。"):
                self.select_image()
                new_text, new_is_image = self.current_image_path or text, True
            else:
                new_text, new_is_image = simpledialog.askstring("编辑文字", "输入新的文字内容:", initialvalue="") or "", False
        else:
            new_text, new_is_image = simpledialog.askstring("编辑文字", "输入新的文字内容:", initialvalue=text) or text, False

        self.points[index] = (new_x, new_y, new_text, click_type, delay_after, new_is_image)
        self.update_points_display()

    def test_input(self):
        if self.input_method_var.get() == "image":
            if not self.current_image_path:
                messagebox.showwarning("警告", "请先选择图片")
                return

            messagebox.showinfo("测试", "5秒后将开始测试图片输入，请将鼠标移动到要测试的输入框")
            time.sleep(5)

            if self.copy_image_to_clipboard(self.current_image_path):
                pyautogui.hotkey('ctrl', 'v')
                print(f"已输入图片: {os.path.basename(self.current_image_path)}")
            else:
                messagebox.showerror("错误", "图片输入测试失败")
        else:
            test_text = simpledialog.askstring("测试输入", "请输入要测试的文本:")
            if not test_text:
                return

            messagebox.showinfo("测试", "5秒后将开始测试输入，请将鼠标移动到要测试的输入框")
            time.sleep(5)

            if self.input_method_var.get() == "paste":
                pyperclip.copy(test_text)
                pyautogui.hotkey('ctrl', 'v')
                print(f"已使用粘贴方式输入: '{test_text}'")
            else:
                if self.clear_before_input.get():
                    pyautogui.hotkey('ctrl', 'a')
                    time.sleep(0.1)
                    pyautogui.press('backspace')
                    time.sleep(0.1)

                pyautogui.write(test_text, interval=0.05)
                print(f"已使用键盘输入方式输入: '{test_text}'")

            if self.enter_after_input.get():
                time.sleep(0.2)
                pyautogui.press('enter')

        messagebox.showinfo("测试完成", "输入测试已完成，请检查目标输入框是否显示了测试内容")

    def start_execution(self):
        self.is_running = True
        self.execute_btn.config(state=tk.DISABLED)
        self.stop_btn.config(state=tk.NORMAL)
        self.record_btn.config(state=tk.DISABLED)

        delay = int(self.global_delay_var.get())
        interval = float(self.global_interval_var.get())

        thread = threading.Thread(target=self.execute_all_actions, args=(delay, interval))
        thread.daemon = True
        thread.start()

    def stop_execution(self):
        self.is_running = False
        self.status_label.config(text="已停止")

    def execute_all_actions(self, delay, interval):
        for i in range(delay, 0, -1):
            if not self.is_running:
                break
            self.update_status(f"{i}秒后开始执行操作...")
            time.sleep(1)

        if not self.is_running:
            self.reset_buttons()
            return

        self.update_status("开始执行操作...")

        for i, (x, y, text, click_type, delay_after, is_image) in enumerate(self.points):
            if not self.is_running:
                break

            self.update_status(f"执行操作 {i + 1}/{len(self.points)}")

            # 执行点击
            click_actions = {
                "单击": pyautogui.click,
                "双击": pyautogui.doubleClick,
                "右键点击": pyautogui.rightClick
            }
            click_actions[click_type](x, y)
            print(f"已{click_type}点 {i + 1}: ({x}, {y})")

            time.sleep(delay_after)

            # 输入内容
            if text:
                self.perform_input(text, is_image)

            if i < len(self.points) - 1 and self.is_running:
                time.sleep(interval)

        if self.is_running:
            self.update_status(f"已完成 {len(self.points)} 个操作")
            self.show_message("完成", f"已执行 {len(self.points)} 个操作")
        else:
            self.update_status("已停止")

        self.reset_buttons()

    def perform_input(self, text, is_image=False):
        if is_image:
            if self.copy_image_to_clipboard(text):
                pyautogui.hotkey('ctrl', 'v')
                print(f"已输入图片: {os.path.basename(text)}")
        else:
            if self.input_method_var.get() == "paste":
                pyperclip.copy(text)
                pyautogui.hotkey('ctrl', 'v')
                print(f"已使用粘贴方式输入: '{text}'")
            else:
                if self.clear_before_input.get():
                    pyautogui.hotkey('ctrl', 'a')
                    time.sleep(0.1)
                    pyautogui.press('backspace')
                    time.sleep(0.1)

                pyautogui.write(text, interval=0.05)
                print(f"已使用键盘输入方式输入: '{text}'")

            if self.enter_after_input.get():
                time.sleep(0.2)
                pyautogui.press('enter')

    def update_status(self, text):
        self.root.after(0, lambda: self.status_label.config(text=text))

    def show_message(self, title, message):
        self.root.after(0, lambda: messagebox.showinfo(title, message))

    def reset_buttons(self):
        self.root.after(0, self._reset_buttons)

    def _reset_buttons(self):
        self.is_running = False
        self.execute_btn.config(state=tk.NORMAL)
        self.stop_btn.config(state=tk.DISABLED)
        self.record_btn.config(state=tk.NORMAL)

    def clear_points(self):
        self.points.clear()
        self.update_points_display()
        self.execute_btn.config(state=tk.DISABLED)

    def open_excel_tool(self):
        if not PANDAS_AVAILABLE or not OPENPYXL_AVAILABLE:
            messagebox.showerror("错误", "请先安装pandas和openpyxl库:\npip install pandas openpyxl")
            return

        ExcelGroupingTool(self.root, self)

    def set_excel_data(self, excel_data):
        self.excel_data = excel_data
        self.excel_execute_btn.config(state=tk.NORMAL)
        messagebox.showinfo("成功", f"已接收 {len(excel_data['data'])} 条数据")
        self.status_label.config(text=f"已加载Excel数据: {len(excel_data['data'])} 行")

    def start_excel_execution(self):
        if not hasattr(self, 'excel_data') or not self.excel_data:
            messagebox.showwarning("警告", "请先导入Excel数据")
            return

        self.is_excel_execution_running = True
        self.excel_execute_btn.config(state=tk.DISABLED)
        self.stop_excel_execute_btn.config(state=tk.NORMAL)
        self.execute_btn.config(state=tk.DISABLED)
        self.record_btn.config(state=tk.DISABLED)

        delay = int(self.global_delay_var.get())
        interval = float(self.global_interval_var.get())

        thread = threading.Thread(target=self.execute_excel_data, args=(delay, interval))
        thread.daemon = True
        thread.start()

    def stop_excel_execution(self):
        self.is_excel_execution_running = False
        self.status_label.config(text="Excel执行已停止")

    def execute_excel_data(self, delay, interval):
        for i in range(delay, 0, -1):
            if not self.is_excel_execution_running:
                break
            self.update_status(f"{i}秒后开始执行Excel数据...")
            time.sleep(1)

        if not self.is_excel_execution_running:
            self.reset_excel_execution_buttons()
            return

        configs, data = self.excel_data['configs'], self.excel_data['data']
        config_map = {config['point_index']: config for config in configs}

        self.update_status(f"开始执行Excel数据，共 {len(data)} 行数据")

        for row_index, current_row in enumerate(data):
            if not self.is_excel_execution_running:
                break

            self.update_status(f"执行第 {row_index + 1}/{len(data)} 行数据")

            for point_index, point in enumerate(self.points):
                if not self.is_excel_execution_running:
                    break

                x, y, original_text, click_type, delay_after, is_image = point

                # 执行点击
                click_actions = {
                    "单击": pyautogui.click,
                    "双击": pyautogui.doubleClick,
                    "右键点击": pyautogui.rightClick
                }
                click_actions[click_type](x, y)
                time.sleep(delay_after)

                # 处理输入
                if point_index in config_map:
                    config = config_map[point_index]
                    input_content = None
                    for key in current_row.keys():
                        if str(key).strip() == str(config['column_name']).strip():
                            input_content = current_row[key]
                            break

                    if input_content is not None:
                        if config['input_method'] == "图片输入" and input_content and os.path.exists(str(input_content)):
                            if self.copy_image_to_clipboard(str(input_content)):
                                pyautogui.hotkey('ctrl', 'v')
                                print(f"已输入图片: {os.path.basename(str(input_content))}")
                        elif pd.notna(input_content) and input_content != "":
                            self.perform_excel_input(input_content, config['input_method'])
                elif original_text:
                    self.perform_input(original_text, is_image)

                time.sleep(0.2)

            if row_index < len(data) - 1 and self.is_excel_execution_running:
                time.sleep(interval)

        if self.is_excel_execution_running:
            self.update_status(f"Excel数据执行完成，共执行 {len(data)} 行数据")
            self.show_message("完成", f"Excel数据执行完成，共执行 {len(data)} 行数据")
        else:
            self.update_status(f"Excel数据执行已停止")

        self.reset_excel_execution_buttons()

    def perform_excel_input(self, content, input_method):
        if input_method == "粘贴":
            pyperclip.copy(str(content))
            pyautogui.hotkey('ctrl', 'v')
            print(f"已使用粘贴方式输入: '{content}'")
        else:
            if self.clear_before_input.get():
                pyautogui.hotkey('ctrl', 'a')
                time.sleep(0.1)
                pyautogui.press('backspace')
                time.sleep(0.1)

            pyautogui.write(str(content), interval=0.05)
            print(f"已使用键盘输入方式输入: '{content}'")

        if self.enter_after_input.get():
            time.sleep(0.2)
            pyautogui.press('enter')

    def reset_excel_execution_buttons(self):
        self.root.after(0, self._reset_excel_execution_buttons)

    def _reset_excel_execution_buttons(self):
        self.is_excel_execution_running = False
        self.excel_execute_btn.config(state=tk.NORMAL)
        self.stop_excel_execute_btn.config(state=tk.DISABLED)
        self.execute_btn.config(state=tk.NORMAL)
        self.record_btn.config(state=tk.NORMAL)


class ExcelGroupingTool:
    def __init__(self, root, main_app):
        self.main_app = main_app
        self.window = tk.Toplevel(root)
        self.window.title("Excel数据处理工具")
        self.window.geometry("800x600")
        self.window.transient(root)
        self.window.grab_set()

        self.excel_data = []
        self.df = None
        self.column_names = []
        self.processed_file_path = None
        self.input_configs = []
        self.input_methods = ["粘贴", "键盘", "图片输入"]

        self.create_widgets()

    def create_widgets(self):
        # 文件选择
        file_frame = tk.Frame(self.window)
        file_frame.pack(pady=10, padx=10, fill=tk.X)

        tk.Label(file_frame, text="选择Excel文件:").pack(side=tk.LEFT)
        self.file_path_var = tk.StringVar()
        tk.Entry(file_frame, textvariable=self.file_path_var, width=50).pack(side=tk.LEFT, padx=5)
        tk.Button(file_frame, text="浏览", command=self.browse_file).pack(side=tk.LEFT, padx=5)

        # 设置
        settings_frame = tk.Frame(self.window)
        settings_frame.pack(pady=10, padx=10, fill=tk.X)

        tk.Label(settings_frame, text="数据开始行:").grid(row=0, column=0, padx=5, sticky=tk.W)
        self.start_row_var = tk.StringVar(value="1")
        tk.Entry(settings_frame, textvariable=self.start_row_var, width=5).grid(row=0, column=1, padx=5)

        # 输入配置
        config_frame = ttk.LabelFrame(self.window, text="输入项配置", padding="10")
        config_frame.pack(pady=10, padx=10, fill=tk.X)

        tk.Label(config_frame, text="配置每个输入项: 输入方式、Excel列名、对应主程序记录点").pack(anchor=tk.W)

        columns = ("序号", "输入方式", "Excel列名", "对应记录点")
        self.config_treeview = ttk.Treeview(config_frame, columns=columns, show="headings", height=6)
        for col in columns:
            self.config_treeview.heading(col, text=col)
            self.config_treeview.column(col, width=100)
        self.config_treeview.pack(fill=tk.X, pady=5)

        # 配置操作按钮
        config_btn_frame = tk.Frame(config_frame)
        config_btn_frame.pack(pady=5)

        for text, command in [("添加输入项", self.add_input_config),
                              ("编辑选中项", self.edit_input_config),
                              ("删除选中项", self.delete_input_config)]:
            tk.Button(config_btn_frame, text=text, command=command).pack(side=tk.LEFT, padx=5)

        # 操作按钮
        btn_frame = tk.Frame(self.window)
        btn_frame.pack(pady=20)

        for text, command in [("导入数据到主程序", self.import_to_main),
                              ("处理数据", self.process_data),
                              ("关闭", self.window.destroy)]:
            tk.Button(btn_frame, text=text, command=command).pack(side=tk.LEFT, padx=5)

        # 结果显示
        result_frame = tk.Frame(self.window)
        result_frame.pack(pady=10, padx=10, fill=tk.BOTH, expand=True)

        tk.Label(result_frame, text="处理结果:").pack(anchor=tk.W)
        self.result_text = tk.Text(result_frame, height=12, width=70)
        self.result_text.pack(fill=tk.BOTH, expand=True)

        scrollbar = tk.Scrollbar(self.result_text)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.result_text.config(yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.result_text.yview)

    def add_input_config(self):
        if not self.column_names:
            messagebox.showwarning("警告", "请先加载Excel文件以获取列名")
            return

        self.create_config_dialog("添加输入项配置")

    def edit_input_config(self):
        selection = self.config_treeview.selection()
        if not selection:
            messagebox.showwarning("警告", "请先选择一个配置项")
            return

        self.create_config_dialog("编辑输入项配置", self.config_treeview.index(selection[0]))

    def create_config_dialog(self, title, index=None):
        config_dialog = tk.Toplevel(self.window)
        config_dialog.title(title)
        config_dialog.geometry("400x200")
        config_dialog.transient(self.window)
        config_dialog.grab_set()

        # 获取主程序记录点
        point_options = []
        if hasattr(self.main_app, 'points'):
            for i, (x, y, text, click_type, delay, is_image) in enumerate(self.main_app.points):
                point_text = f"点{i + 1}: ({x},{y})"
                if text:
                    point_text += f" [图片]" if is_image else f" '{text}'"
                point_options.append(point_text)

        # 输入方式
        tk.Label(config_dialog, text="输入方式:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
        input_method_var = tk.StringVar(value="粘贴" if index is None else self.input_configs[index]['input_method'])
        ttk.Combobox(config_dialog, textvariable=input_method_var, values=self.input_methods,
                     state="readonly", width=15).grid(row=0, column=1, padx=5, pady=5)

        # Excel列名
        tk.Label(config_dialog, text="Excel列名:").grid(row=1, column=0, padx=5, pady=5, sticky=tk.W)
        column_var = tk.StringVar()
        if index is not None:
            column_var.set(str(self.input_configs[index]['column_name']))
        ttk.Combobox(config_dialog, textvariable=column_var, values=[str(col) for col in self.column_names],
                     state="readonly", width=15).grid(row=1, column=1, padx=5, pady=5)

        # 对应记录点
        tk.Label(config_dialog, text="对应记录点:").grid(row=2, column=0, padx=5, pady=5, sticky=tk.W)
        point_var = tk.StringVar()
        point_combo = ttk.Combobox(config_dialog, textvariable=point_var, values=point_options,
                                   state="readonly", width=20)
        point_combo.grid(row=2, column=1, padx=5, pady=5)

        if point_options:
            default_index = self.input_configs[index]['point_index'] if index is not None else 0
            point_combo.set(point_options[default_index])

        def confirm_config():
            if not column_var.get():
                messagebox.showwarning("警告", "请选择Excel列名")
                return

            config = {
                'input_method': input_method_var.get(),
                'column_name': column_var.get(),
                'point_index': point_combo.current()
            }

            if index is None:
                self.input_configs.append(config)
            else:
                self.input_configs[index] = config

            self.update_config_display()
            config_dialog.destroy()

        btn_frame = tk.Frame(config_dialog)
        btn_frame.grid(row=3, column=0, columnspan=2, pady=10)

        tk.Button(btn_frame, text="确定", command=confirm_config).pack(side=tk.LEFT, padx=5)
        tk.Button(btn_frame, text="取消", command=config_dialog.destroy).pack(side=tk.LEFT, padx=5)

    def delete_input_config(self):
        selection = self.config_treeview.selection()
        if not selection:
            messagebox.showwarning("警告", "请先选择一个配置项")
            return

        self.input_configs.pop(self.config_treeview.index(selection[0]))
        self.update_config_display()

    def update_config_display(self):
        for item in self.config_treeview.get_children():
            self.config_treeview.delete(item)

        for i, config in enumerate(self.input_configs):
            point_desc = f"点{config['point_index'] + 1}"
            if hasattr(self.main_app, 'points') and config['point_index'] < len(self.main_app.points):
                x, y, text, click_type, delay, is_image = self.main_app.points[config['point_index']]
                point_desc = f"点{config['point_index'] + 1}: ({x},{y})"

            self.config_treeview.insert("", "end", values=(
                i + 1, config['input_method'], config['column_name'], point_desc
            ))

    def browse_file(self):
        file_path = filedialog.askopenfilename(
            title="选择Excel文件",
            filetypes=[("Excel files", "*.xlsx *.xls"), ("All files", "*.*")]
        )
        if file_path:
            self.file_path_var.set(file_path)
            self.load_excel_columns(file_path)

    def load_excel_columns(self, file_path):
        try:
            self.df = pd.read_excel(file_path, engine='openpyxl')
            self.column_names = [str(col) for col in self.df.columns.tolist()]

            self.result_text.delete(1.0, tk.END)
            self.result_text.insert(tk.END, f"成功加载文件: {file_path}\n")
            self.result_text.insert(tk.END, f"找到 {len(self.column_names)} 个列: {', '.join(self.column_names)}\n")
        except Exception as e:
            messagebox.showerror("错误", f"读取Excel文件失败: {str(e)}")
            self.result_text.delete(1.0, tk.END)
            self.result_text.insert(tk.END, f"错误: {str(e)}\n")

    def import_to_main(self):
        if not self.processed_file_path:
            messagebox.showwarning("警告", "请先处理数据")
            return

        try:
            processed_df = pd.read_excel(self.processed_file_path, sheet_name='处理数据', engine='openpyxl')

            if hasattr(self.main_app, 'set_excel_data'):
                import_data = {
                    'configs': self.input_configs,
                    'data': processed_df.to_dict('records')
                }
                self.main_app.set_excel_data(import_data)
                messagebox.showinfo("成功", f"成功导入 {len(processed_df)} 条数据到主程序")

                self.result_text.delete(1.0, tk.END)
                self.result_text.insert(tk.END, f"成功导入 {len(processed_df)} 条数据到主程序:\n")

                for config in self.input_configs:
                    self.result_text.insert(tk.END,
                                            f"- {config['input_method']}: {config['column_name']} -> 点{config['point_index'] + 1}\n")
            else:
                messagebox.showerror("错误", "主程序不支持Excel数据导入")
        except Exception as e:
            messagebox.showerror("错误", f"读取处理数据失败: {str(e)}\n请先点击'处理数据'按钮")

    def process_data(self):
        if not hasattr(self, 'df') or self.df is None:
            messagebox.showerror("错误", "请先选择有效的Excel文件")
            return

        if not self.input_configs:
            messagebox.showerror("错误", "请至少添加一个输入项配置")
            return

        try:
            self.df.columns = [str(col) for col in self.df.columns]

            for config in self.input_configs:
                if str(config['column_name']) not in self.df.columns:
                    messagebox.showerror("错误", f"列 '{config['column_name']}' 不存在")
                    return

            start_row = max(int(self.start_row_var.get()) - 1, 0)
            df_filtered = self.df.iloc[start_row:].copy()

            output_data = []
            for index, row in df_filtered.iterrows():
                row_data = {'行号': index + 2}
                for config in self.input_configs:
                    row_data[config['column_name']] = row[config['column_name']] if pd.notna(
                        row[config['column_name']]) else ""
                output_data.append(row_data)

            output_df = pd.DataFrame(output_data)
            new_file_path = self.file_path_var.get().replace('.xlsx', '_处理结果.xlsx')

            with pd.ExcelWriter(new_file_path, engine='openpyxl') as writer:
                output_df.to_excel(writer, sheet_name='处理数据', index=False)

            self.processed_file_path = new_file_path
            messagebox.showinfo("成功", f"处理完成！共处理 {len(output_df)} 行数据\n数据已保存到: {new_file_path}")
            self.display_results(output_df)

        except Exception as e:
            messagebox.showerror("错误", f"处理失败: {str(e)}")

    def display_results(self, df):
        self.result_text.delete(1.0, tk.END)
        self.result_text.insert(tk.END, f"处理完成！共 {len(df)} 行数据\n\n输入项配置:\n")

        for i, config in enumerate(self.input_configs):
            self.result_text.insert(tk.END,
                                    f"{i + 1}. {config['input_method']} -> {config['column_name']} -> 点{config['point_index'] + 1}\n")

        self.result_text.insert(tk.END, "\n" + "=" * 50 + "\n\n")

        for i, (_, row) in enumerate(df.head(5).iterrows()):
            self.result_text.insert(tk.END, f"行 {row['行号']}:\n")
            for config in self.input_configs:
                value = row[config['column_name']]
                if pd.notna(value) and value != "":
                    self.result_text.insert(tk.END, f"- {config['column_name']}: {value}\n")
            self.result_text.insert(tk.END, "-" * 30 + "\n\n")

        if len(df) > 5:
            self.result_text.insert(tk.END, f"... 还有 {len(df) - 5} 行数据未显示\n")


def main():
    root = tk.Tk()
    app = ClickPointsApp(root)
    root.mainloop()


if __name__ == "__main__":
    main()